﻿using OpenCvSharp;
using OpenCvSharp.WpfExtensions;
using PLCSharp.CoreModel.Common;
using PLCSharp.CoreModel.Prism;
using PLCSharp.CoreModel.UserControls;
using PLCSharp.Models;
using PLCSharp.Views.Connects;
using PLCSharp.Views.GlobalVariables;
using PLCSharp.Views.Vision.Camera;
using PLCSharp.Views.Vision.opencv;
using Prism.Commands;
using Prism.Dialogs;
using Prism.Events;
using Prism.Ioc;
using System.Collections.ObjectModel;
using System.Diagnostics;
using System.Threading;
using System.Windows.Controls;

using System.Windows.Media.Imaging;

namespace PLCSharp.Views.Vision
{
    public class VisionConfigViewModel : DialogAwareBase
    {
        public VisionConfigViewModel(IContainerExtension container, IEventAggregator ea, IDialogService dialogService) : base(container, ea, dialogService)
        {
            VisionsModel = container.Resolve<VisionsModel>();
            Variables = container.Resolve<VariablesModel>().Variables;
            Connects = container.Resolve<ConnectsModel>();
            GlobalModel = container.Resolve<GlobalModel>();
        }
        public ConnectsModel Connects { get; set; }
        public GlobalModel GlobalModel { get; set; }
        public ObservableCollection<Variable> Variables { get; set; }
        private CameraBase _SelectedCamera;
        public CameraBase SelectedCamera
        {
            get { return _SelectedCamera; }
            set
            {
                SetProperty(ref _SelectedCamera, value);
                if (value != null)
                    SelectVisionFlow.StringParams["Camera"] = value.Name;

            }
        }
        private Variable _SelectedVariable;
        public Variable SelectedVariable
        {
            get { return _SelectedVariable; }
            set
            {
                SetProperty(ref _SelectedVariable, value);
                if (value != null)
                    SelectVisionFlow.StringParams["Variable"] = value.Name;
            }
        }
        public override void OnDialogOpened(IDialogParameters parameters)
        {
            SelectedVisionFunction = parameters.GetValue<VisionFunction>("SelectedVisionFunction");

        }
        private ImageData _SelectImageData;
        /// <summary>
        /// 
        /// </summary>
        public ImageData SelectImageData
        {
            get { return _SelectImageData; }
            set
            {
                SetProperty(ref _SelectImageData, value);
                if (value != null)

                    SelectVisionFlow.StringParams.Add("Image", value.Name);


            }
        }
        private UserControl _ContentRegion;
        /// <summary>
        /// 
        /// </summary>
        public UserControl ContentRegion
        {
            get { return _ContentRegion; }
            set { SetProperty(ref _ContentRegion, value); }
        }
        public VisionsModel VisionsModel { get; set; }

        private VisionFunction _SelectedVisionFunction;
        /// <summary>
        /// 
        /// </summary>
        public VisionFunction SelectedVisionFunction
        {
            get { return _SelectedVisionFunction; }
            set { SetProperty(ref _SelectedVisionFunction, value); }
        }

        private VisionFlow _SelectVisionFlow;
        /// <summary>
        /// 
        /// </summary>
        public VisionFlow SelectVisionFlow
        {
            get { return _SelectVisionFlow; }
            set
            {
                SetProperty(ref _SelectVisionFlow, value);
                ContentRegion = null;
                if (_SelectVisionFlow != null)
                {
                    _SelectVisionFlow_TypeChanged();

                }
            }
        }

        private void _SelectVisionFlow_TypeChanged()
        {
            ContentRegion = null;
            switch (_SelectVisionFlow.Type)
            {
                case VisionFlowType.从图像池获取图片:
                case VisionFlowType.存到图像池:
                    ContentRegion = new ImagesPool();
                    if (SelectVisionFlow.StringParams.TryGetValue("Image", out string value))
                    {
                        SelectImageData = VisionsModel.ImageDatas.Where(c => c.Name == value).FirstOrDefault();

                    }
                    break;
                case VisionFlowType.从文件获取图片:
                    ContentRegion = new ImageFromFile();
                    break;
                case VisionFlowType.从相机获取图片:
                    ContentRegion = new ImageFromCamera();
                    if (SelectVisionFlow.StringParams.TryGetValue("Camera", out string cameraName))
                    {
                        SelectedCamera = VisionsModel.Cameras.Where(c => c.Name == cameraName).FirstOrDefault();

                    }
                    break;
                case VisionFlowType.二值化:

                    if (SelectVisionFlow.IntParams.TryGetValue("ThresholdType", out _) == false)
                    {
                        SelectVisionFlow.IntParams["ThresholdType"] = 0;
                        SelectVisionFlow.IntParams["Threshold"] = 100;
                        SelectVisionFlow.IntParams["MaxValue"] = 255;
                        SelectVisionFlow.BoolParams["IsOtsu"] = false;
                        SelectVisionFlow.BoolParams["IsTriangle"] = false;

                    }
                    ContentRegion = new Threshold();

                    break;
                case VisionFlowType.GRAY2BGR:
                    break;
                case VisionFlowType.BGR2GRAY:
                    break;
                case VisionFlowType.取B通道:
                    break;
                case VisionFlowType.取G通道:
                    break;
                case VisionFlowType.取R通道:
                    break;
                case VisionFlowType.存到文件:
                    ContentRegion = new ImageToFile();
                    break;
                case VisionFlowType.各通道最小值:
                    break;
                case VisionFlowType.各通道最大值:
                    break;
                case VisionFlowType.显示图像到主页:
                    ContentRegion = new ImageToHomePage();
                    break;
            }

            if (ContentRegion != null)
                ContentRegion.DataContext = this;
        }

        private DelegateCommand<string> _Manage;
        public DelegateCommand<string> Manage =>
            _Manage ??= new DelegateCommand<string>(ExecuteManage);

        void ExecuteManage(string cmd)
        {
            switch (cmd)
            {
                case "新增":
                    var newFlow = new VisionFlow();
                    SelectedVisionFunction.VisionFlows.Add(newFlow);
                    if (SelectVisionFlow != null)
                    {
                        var selectIndex = SelectedVisionFunction.VisionFlows.IndexOf(SelectVisionFlow);
                        var currentIndex = SelectedVisionFunction.VisionFlows.IndexOf(newFlow);
                        SelectedVisionFunction.VisionFlows.Move(currentIndex, selectIndex + 1);

                    }
                    SelectVisionFlow = newFlow;
                    SelectImageData = null;
                    break;
                case "删除":

                    if (SelectVisionFlow != null && SelectedVisionFunction.VisionFlows.Contains(SelectVisionFlow))
                    {

                        SelectedVisionFunction.VisionFlows.Remove(SelectVisionFlow);

                    }

                    break;

                case "上移":
                    if (SelectVisionFlow != null && SelectedVisionFunction.VisionFlows.IndexOf(SelectVisionFlow) > 0)
                    {

                        var currentIndex = SelectedVisionFunction.VisionFlows.IndexOf(SelectVisionFlow);
                        SelectedVisionFunction.VisionFlows.Move(currentIndex, currentIndex - 1);

                    }

                    break;

                case "下移":
                    if (SelectVisionFlow != null && SelectedVisionFunction.VisionFlows.IndexOf(SelectVisionFlow) < SelectedVisionFunction.VisionFlows.Count - 1)
                    {

                        var currentIndex = SelectedVisionFunction.VisionFlows.IndexOf(SelectVisionFlow);
                        SelectedVisionFunction.VisionFlows.Move(currentIndex, currentIndex + 1);
                    }


                    break;
            }
        }

        private DelegateCommand _CreatROI;
        public DelegateCommand CreatROI =>
            _CreatROI ??= new DelegateCommand(ExecuteCreatROI);

        void ExecuteCreatROI()
        {
            if (Drawing)
            {

                return;
            }
            Drawing = true;
        }

        private AsyncDelegateCommand _TestSelect;
        public AsyncDelegateCommand TestSelect =>
            _TestSelect ??= new AsyncDelegateCommand(ExecuteTestSelectAsync);

        private async Task ExecuteTestSelectAsync()
        {
            try
            {

                await Task.Run(() =>
                {
                    SelectVisionFlow.Flow.Reset();

                    while (true)
                    {
                        Thread.Sleep(1);
                        if (SelectedVisionFunction.RunItem(SelectVisionFlow))
                        {
                            return;
                        }
                        else if (SelectVisionFlow.Flow.CheckFlowTime(10))
                        {
                            throw new Exception("流程超时!");

                        }
                    }



                });
            }
            catch (Exception ex)
            {

                SendErr(ex.Message, ErrType.ShowDialogAndRecord);
            }


            if (SelectedVisionFunction.Src == null) return;

            ShowMat = SelectedVisionFunction.Src;
        }


        private AsyncDelegateCommand<object> _Calibration;
        public AsyncDelegateCommand<object> Calibration =>
            _Calibration ??= new AsyncDelegateCommand<object>(ExecuteCalibrationAsync);

        private async Task ExecuteCalibrationAsync(object param)
        {
            var imageEdit = param as ImageEdit;
            if (imageEdit == null || imageEdit.ImageSource == null)
                return;
            var roi = await imageEdit.DrawROIAsync();

            Debug.Write(roi);
        }
        private AsyncDelegateCommand _TestFunction;
        public AsyncDelegateCommand TestFunction =>
            _TestFunction ??= new AsyncDelegateCommand(ExecuteTestFunctionAsync);

        private async Task ExecuteTestFunctionAsync()
        {
            try
            {
                await Task.Run(() =>
                {
                    var runAllFlow = new FlowModel();
                    while (true)
                    {
                        Thread.Sleep(1);
                        if (SelectedVisionFunction.RunAll(runAllFlow))
                        {
                            return;
                        }
                        else if (runAllFlow.CheckFlowTime(10))
                        {
                            throw new Exception("流程超时!");

                        }
                    }
                });

            }
            catch (Exception ex)
            {

                SendErr(ex.Message, ErrType.ShowDialogAndRecord);
            }
            if (SelectedVisionFunction.Src == null) return;

            ShowMat = SelectedVisionFunction.Src;
        }
        private DelegateCommand _Save;
        public DelegateCommand Save =>
            _Save ??= new DelegateCommand(ExecuteSave);

        void ExecuteSave()
        {
            VisionsModel.Manage.Execute("Save");
        }


        private bool _Drawing;
        /// <summary>
        /// 
        /// </summary>
        public bool Drawing
        {
            get { return _Drawing; }
            set { SetProperty(ref _Drawing, value); }
        }

        private WriteableBitmap _ImgSrc;

        public WriteableBitmap ImgSrc
        {
            get { return _ImgSrc; }
            set { SetProperty(ref _ImgSrc, value); }
        }
        private Mat _ShowMat;
        /// <summary>
        /// 
        /// </summary>
        public Mat ShowMat
        {
            get { return _ShowMat; }
            set
            {
                SetProperty(ref _ShowMat, value);
                if (value == null) return;
                System.Windows.Application.Current.Dispatcher.Invoke(new Action(() =>
                {
                    try
                    {
                        if (_ImgSrc != null
                   && _ShowMat.Width == _ImgSrc.PixelWidth
                   && _ShowMat.Height == _ImgSrc.PixelHeight
                   && _ShowMat.Channels() == _ImgSrc.Format.BitsPerPixel / 8
                       )
                        {
                            WriteableBitmapConverter.ToWriteableBitmap(_ShowMat, _ImgSrc);

                        }
                        else
                        {
                            ImgSrc = WriteableBitmapConverter.ToWriteableBitmap(_ShowMat);
                        }
                    }
                    catch (Exception)
                    {


                    }

                }));


            }
        }

        #region 


        private DelegateCommand<string> _ImageFile;
        public DelegateCommand<string> ImageFile =>
            _ImageFile ??= new DelegateCommand<string>(ExecuteImageFile);

        void ExecuteImageFile(string cmd)
        {
            switch (cmd)
            {
                case "Open":
                    {
                        Microsoft.Win32.OpenFileDialog ofd = new()
                        {
                            DefaultExt = ".*",
                            Filter = "图像文件(*.jpg;*.png;*.bmp)|*.jpg;*.png;*.bmp"
                        };
                        if (ofd.ShowDialog() == true)
                        {
                            try
                            {
                                SelectedVisionFunction.Src = Cv2.ImRead(ofd.FileName);
                                if (!SelectedVisionFunction.Src.Empty())
                                {
                                    SelectVisionFlow.StringParams["Path"] = ofd.FileName;

                                    ShowMat = SelectedVisionFunction.Src;
                                }
                                else
                                    SendErr("不支持的图像格式", ErrType.ShowDialog);
                            }
                            catch (Exception ex)
                            {
                                SendErr($"读取图像异常 - {ex.Message}", ErrType.ShowDialog);

                            }
                        }
                    }
                    break;
                case "Save":
                    {

                        Microsoft.Win32.OpenFileDialog openFileDialog = new()
                        {
                            Title = "选择文件夹",
                            Filter = "文件夹|*.directory",
                            FileName = "选择此文件夹",

                            ValidateNames = false,
                            CheckFileExists = false,
                            CheckPathExists = true,
                            Multiselect = true,//允许同时选择多个文件
                            InitialDirectory = "D:"//指定启动路径
                        };
                        if (openFileDialog.ShowDialog() == true)

                        {
                            var path = openFileDialog.FileName.Replace("选择此文件夹.directory", "");

                            if (!System.IO.Directory.Exists(path))
                            {
                                System.Windows.MessageBox.Show(path + "文件夹不存在", "选择文件提示");
                                return;
                            }


                            SelectVisionFlow.StringParams["Path"] = path;
                        }
                    }


                    break;
            }
        }


        #endregion

        private VisionType _Type;
        /// <summary>
        /// 
        /// </summary>
        public VisionType Type
        {
            get { return _Type; }
            set { SetProperty(ref _Type, value); }
        }
    }
}
